package com.order.manager.controller.User;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.order.manager.Model.SenderInfo;
import com.order.manager.Model.UserInfo;
import com.order.manager.Model.other.LoginRequest;
import com.order.manager.Model.other.Options;
import com.order.manager.Model.other.RestBean;
import com.order.manager.service.AuthUserDetailService;
import com.order.manager.service.impl.OrderInfoServiceImpl;
import com.order.manager.service.impl.SenderInfoServiceImpl;
import com.order.manager.service.impl.UserInfoServiceImpl;
import com.order.manager.util.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 24862
 */
@RestController
@RequestMapping("api/auth")
@Slf4j
public class UserLoginController {

    @Resource
    JwtUtil jwtUtil;
    @Resource
    AuthenticationManager authenticationManager;

    @Resource
    AuthUserDetailService authUserDetailService;

    @Resource
    UserInfoServiceImpl userInfoService;

    @Resource
    PasswordEncoder passwordEncoder;

    @Resource
    OrderInfoServiceImpl orderInfoService;

    @Resource
    SenderInfoServiceImpl senderInfoService;


    /**
     * 携带参数Json
     * {
     * "username":"poxiaodi",
     * "password":"poxiaodi1314"
     * }
     * 返回token
     */
    @PostMapping("login")
    public RestBean doLogin(@RequestBody LoginRequest request) {
        try {
            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword());
            Authentication authentication = authenticationManager.authenticate(auth);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("username", userDetails.getUsername()).eq("state", 1));//通过用户名来获取该用户的所有登录信息
            String jwtToken = jwtUtil.getToken(userInfo.getUserId());//通过uuid来jwt生成获取token
//            String userUUID = userInfo.getUserId();
//            jedisUtil.setNewVal(2, userUUID, jwtToken);//通过userId来存储
            return RestBean.success(jwtToken);
        } catch (Exception e) {
            log.error(e.getMessage());
            log.error("username or password is not correct");
            return RestBean.failure(401, "登录失败");
        }
    }


    /**
     * 角色判断
     * school
     * student
     * student_sender
     * shop
     *
     * @param request
     * @return
     */
    //学校
    @RequestMapping("/school/check")
    public RestBean schoolCheck(HttpServletRequest request) {
        return roleFlag(request, "school");
    }

    //学生
    @RequestMapping("/student/check")
    public RestBean studentCheck(HttpServletRequest request) {
        return roleFlag(request, "student");
    }

    //学生兼配送员
    @RequestMapping("/student_sender/check")
    public RestBean studentSenderCheck(HttpServletRequest request) {
        return roleFlag(request, "student_sender");
    }

    //商家
    @RequestMapping("/shop/check")
    public RestBean shopCheck(HttpServletRequest request) {
        return roleFlag(request, "shop");
    }


    @RequestMapping("/student/student_sender/check")
    public RestBean checkStudentStudentSender(HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUsername(request);
        if (userInfoService.getById(uuid).getIsEnable() != 1) {
            return RestBean.failure(403, "该用户已被禁用");
        }
        String token = jwtUtil.getToken(uuid);
        return RestBean.success(token);
    }

    //角色判断，并返回新的token
    public RestBean roleFlag(HttpServletRequest request, String role) {
        String uuid = jwtUtil.getJwtUsername(request);
        log.info(uuid);
        if (uuid.isEmpty()) {
            return RestBean.failure(403, "请重新登录");
        }
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("user_id", uuid));
        if (userInfo == null) {
            return RestBean.failure(403, "没有此用户");
        }
        if (!userInfo.getRole().equals(role)) {
            return RestBean.failure(403, "token异常，Full auth");
        }
        String token = jwtUtil.getToken(uuid);
        return RestBean.success(token);
    }


    /**
     * 传递参数包含
     * {
     * "username":"test233",
     * "password":"test",
     * "name":"测试账号1",
     * "role":"student",
     * "address":"北京市",
     * "phone":"8748273894",
     * "sex":"男"
     * }
     *
     * @param user
     * @return
     */

    @PostMapping("/register")
    public RestBean doUserRegister(@RequestBody UserInfo user) {
        if (user.getUsername() == null || user.getUsername().isEmpty()) {
            return RestBean.failure(403, "用户名不能为空");
        }
        try {
            if (user.getPassword() != null && !user.getPassword().isEmpty()) {
                String password = passwordEncoder.encode(user.getPassword());
                //存储数据库中的密码要进行加密处理
                user.setPassword(password);
                UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("username", user.getUsername()));//用户名不可重复

                if (userInfo == null) {
                    if (!(user.getRole().equals("school") || user.getRole().equals("student") || user.getRole().equals("student_sender") || user.getRole().equals("shop"))) {
                        return RestBean.failure(403, "角色权限分配错误");
                    }

                    if (user.getName() == null || user.getName().isEmpty()) {
                        user.setName(user.getUsername());
                    }
                    authUserDetailService.insertUser(user);
                    String jwtToken = jwtUtil.getToken(user.getUserId());//这里也采用uuid返回jwt
                    return RestBean.success(jwtToken);
                } else {
                    log.info("Username:" + user.getUsername() + "is exists");
                    return RestBean.failure(403, "该用户已存在，请重新输入用户名");
                }
            } else {
                log.info("密码不能为空");
                return RestBean.failure(403, "密码不能为空");
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            return RestBean.failure(403, "注册失败");
        }

    }

    /**
     * 用户更新自己的信息
     *
     * @param userLoginInfo
     * @param httpServletRequest
     * @return
     */
    @RequestMapping("update/user")
    public RestBean updateUserInfoByUserSelf(@RequestBody UserInfo userLoginInfo, HttpServletRequest httpServletRequest) {
        log.info(userLoginInfo.toString());
        try {
            String jwtUsername = jwtUtil.getJwtUsername(httpServletRequest);//获取uuid
            log.info(jwtUsername);
            UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("user_id", jwtUsername).eq("state", "1"));//通过请求人的uuid来获取
            if (userInfo != null) {//用来查看是否存在该用户
                userLoginInfo.setUpdateTime(new Date());//设置更新时间
                userLoginInfo.setUserId(jwtUsername);//来获取jwt里面的uuid
                userLoginInfo.setPassword(userInfo.getPassword());//这里不能直接修改密码，修改密码到必须专门的接口来修改
                userLoginInfo.setInputTime(userInfo.getInputTime());//账号创建时间不可修改
                userLoginInfo.setIsEnable(userInfo.getIsEnable());//账号状态不可从这里修改,有专门的接口来进行初始化操作。
                userLoginInfo.setState(userInfo.getState());//账号是否禁用不可在这里修改
                userLoginInfo.setRole(userInfo.getRole());//角色信息不可以修改，后续可以完善，比如商家版本
                userLoginInfo.setUsername(userInfo.getUsername());//用户账号必须通过专门的接口写，不可以直接更改，防重
                //密码、邮箱、账号、余额都必须专门的接口来写，不可以直接修改
                //查看是否存在该用户设置的用户名，或者该人就是这个用户名
                boolean updateById = userInfoService.updateById(userLoginInfo);
                if (updateById) {
                    return RestBean.success(userLoginInfo);
                }
                return RestBean.failure(500, "更新失败");
            } else {
                return RestBean.failure(403, "jwt uuid error | user is unEnable");//不存在该uuid
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            return RestBean.failure(500, "更新用户信息失败");
        }
    }

    @RequestMapping("/password/forget")
    public RestBean updateByEmail(@RequestBody LoginRequest request) {
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("username", request.getUsername()));
        if (userInfo != null) {
            userInfo.setPassword(passwordEncoder.encode(request.getPassword()));//更新密码
            userInfo.setUpdateTime(new Date());//更新时间
            return userInfoService.updateById(userInfo) ? RestBean.success(jwtUtil.getToken(request.getUsername())) : RestBean.failure(500, "更新失败");
        }
        return RestBean.failure(403, "没有该用户");
    }

    @RequestMapping("/add/money/{money}")
    public RestBean addUserMoney(@PathVariable Double money, HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUsername(request);
        UserInfo userInfo = userInfoService.getById(uuid);
        double moneyTotal = Double.valueOf(userInfo.getMoney()) + money;
        userInfo.setMoney(String.valueOf(moneyTotal));
        return userInfoService.updateById(userInfo) ? RestBean.success(userInfo) : RestBean.failure(500, "充值失败");
    }

    @RequestMapping("update/admin")//要返回该用户的uuid
    public RestBean updateUserInfoByAdmin(@RequestBody UserInfo userLoginInfo) {
        try {
            boolean flag = false;//定义一个标识符来查看是否存在该用户的uuid
            List<UserInfo> userLoginInfos = userInfoService.list();
            for (UserInfo loginInfo : userLoginInfos) {
                if (loginInfo.getUsername().equals(userLoginInfo.getUsername())) {
                    return RestBean.failure(403, "用户名已存在");
                }
                if (userLoginInfo.getUserId().equals(loginInfo.getUserId())) {
                    flag = true;
                }
            }//查看用户名是否存在
            if (flag && (userInfoService.updateById(userLoginInfo))) {//如果更新成功那么返回
                return RestBean.success(userInfoService.getById(userLoginInfo.getUserId()));
            }
            return RestBean.failure(500, "更新失败");
        } catch (Exception e) {
            log.info(e.getMessage());
            return RestBean.failure(500, "更新用户信息失败");
        }
    }


    @RequestMapping("/userinfo")
    public RestBean getUserInfo(HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUsername(request);
        if (uuid.isEmpty()) {
            return RestBean.failure(500, "没有此用户");
        }
        UserInfo info = userInfoService.getById(uuid);
        if (info == null) {
            return RestBean.failure(403, "没有此用户");
        }
        return RestBean.success(info);
    }

    @RequestMapping("/set/username")
    public RestBean setUsername(String username, HttpServletRequest request) {
        String jwtUsername = jwtUtil.getJwtUsername(request);//获取用户的uuid
        UserInfo userInfo = userInfoService.getById(jwtUsername);//通过id获取该用户
        if (userInfo != null) {//如果该用户修改的用户名不为本身，而且该用户存在
            if (userInfo.getUsername().equals(username)) {
                return RestBean.success(username);//如果该用户修改的用户名是本身，那就不做修改
            }
            UserInfo info = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("username", username));
            if (info != null && info.getState() == 1) {
                return RestBean.failure(403, "该账户名已存在,请重新命名");
            }
            userInfo.setUsername(username);
            if (userInfoService.updateById(userInfo)) {
                return RestBean.success(username);
            }
            return RestBean.failure(500, "更新账号信息失败");
        }
        return RestBean.failure(403, "非法修改!");//不存在该用户
    }


    @RequestMapping("/user/list")
    public RestBean userList() {
        List<UserInfo> userLoginInfos = userInfoService.list(new QueryWrapper<UserInfo>().eq("state", '1'));
        List<Options> options = new ArrayList<>();
        for (UserInfo u : userLoginInfos) {
            Options o = new Options(u.getUserId(), u.getUsername());
            options.add(o);
        }
        return RestBean.success(options);
    }


    @RequestMapping("/student/count")
    public RestBean studentCount() {
        return RestBean.success(userInfoService.getStudentCount());
    }

    @RequestMapping("/order/count")
    public RestBean orderCount() {
        return RestBean.success(orderInfoService.list().size());
    }

    @RequestMapping("/sender/count")
    public RestBean senderCount() {
        return RestBean.success(senderInfoService.count(new QueryWrapper<SenderInfo>()
                .eq("is_pass", 1)
        ));
    }

}
